package hu.uszeged.inf.stud.prf.todo.dao.core;

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;

/**
 * Generic Data Access Object implementation. Do not implement it directly.
 * @author Hibernate
 * @author akerekes
 * @author rosand
 * @author zoliver
 * @param <T> Type you want to access
 * @param <ID> Type you want to use as id
 */
public interface GenericDAO<T, ID extends Serializable>
{

   /**
    * Find an entity by id.
    * 
    * @param id by id
    * @param lock can be lock
    * @return the entity if it exists, null if not
    */
   public T findById(ID id, boolean lock);

   /**
    * Find a list contains entities by an examples instance, exclude the exclude properties.
    * 
    * @param exampleInstance by the example instance
    * @param excludeProperty exclude properties list
    * @return the entity list
    */
   public List<T> findByExample(T exampleInstance, String[] excludeProperty);

   /**
    * Make persistent a T type entity.
    * 
    * @param entity the entity
    * @return the persisted entity
    */
   public T makePersistent(T entity);

   /**
    * Save an entity immediately into to the datastore, no matter its in or out of the transaction.
    * 
    * @param entity the entity be saved
    * @return the saved entity identify
    */
   public ID save(T entity);

   /**
    * Make persistent an entity if it wasn't and update immediately.
    * 
    * @param entity the entity be updated
    */
   public void update(T entity);

   /**
    * Make a transient instance persistent.
    * 
    * @param entity a transient instance to be made persistent
    */
   public void persist(T entity);

   /**
    * Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently
    * associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and
    * return it as a newly persistent instance. The given instance does not become associated with the session
    * 
    * @param entity a detached instance with state to be copied
    * @return an updated persistent instance
    */
   public T merge(T entity);

   /**
    * Delete an entity from the datastore.
    * 
    * @param entity the entity will be deleted
    */
   public void makeTransient(T entity);

   /**
    * This method says that the entity is transient.
    * 
    * @param entity the entity will be queried
    * @return true if the entity is not persistent, namely transient
    */
   public boolean isTransient(final T entity);

   /**
    * This method says that the entity is persistent.
    * 
    * @param entity the entity will be queried
    * @return true if the entity is persistent, namely not transient
    */
   public boolean isPersistent(final T entity);

   /**
    * Force this hibernate session to flush. Must be called at the end of a unit of work, before commiting the transaction and closing the
    * session.
    */
   public void flush();

   /**
    * Completely clear the hibernate session.
    */
   public void clear();

   /**
    * Remove this instance from the session cache. Changes to the instance will not be synchronized with the database. This operation
    * cascades to associated instances if the association is mapped with cascade="evict".
    * 
    * @param entity a persistent instance
    */
   public void evict(T entity);

   /**
    * Find entities by a criteria.
    * 
    * @param criterion the restrictions, projections, etc
    * @return the list of the entities
    */
   public List<T> findByCriteria(Criterion... criterion);

   /**
    * Find and order entities by a criteria.
    * 
    * @param criterion
    * @param order
    * @return
    */
   public List<T> findByCriteria(Criterion[] criterion, Order[] order);

   // TODO norm???lis javadoc
   /**
    * Session flush, session clear. Find entities by a criteria.
    * 
    * @param criterion the restrictions, projections, etc
    * @return the list of the entities
    */
   public List<T> findByCriteriaAfterClear(final Criterion... criterion);

   /**
    * Find entities by a criteria. Every entity performs once.
    * 
    * @param criterion the restrictions, projections, etc
    * @return the list of the entities
    */
   public List<T> findByDistinctCriteria(Criterion... criterion);

   /**
    * Find entities by a criteria. Every entity performs once and it can a pageable query.
    * 
    * @param page the begin page
    * @param itemsPerPage count of items per page
    * @param criterion the restrictions, projections, etc
    * @return the list of the entities
    */
   public List<T> findByDistinctPageableCriteria(final int page, final int itemsPerPage, final Criterion... criterion);

   /**
    * Give the count of distinct items by criteria.
    * 
    * @param criterion the criterions
    * @return count of items
    */
   public long countByDistinctCriteria(final Criterion... criterion);

   /**
    * Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running
    * sessions that span many business tasks.
    * 
    * @param object
    */
   public void refresh(final Object object);

}
